home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
memos.zip
/
FILEIO.PRG
< prev
next >
Wrap
Text File
|
1993-03-10
|
9KB
|
359 lines
/***
*
* Fileio.prg
* Sample user-defined functions to process binary files
* Copyright, Nantucket Corporation, 1990
*
* NOTE: compile with /n/w/a/m
*/
#include "Fileio.ch"
/***
* FGets( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cBuffer
* Read one or more lines from a text file
*
*/
FUNCTION FGets(nHandle, nLines, nLineLength, cDelim)
RETURN FReadLn(nHandle, nLines, nLineLength, cDelim)
/***
* FPuts( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
* Write a line to a text file
*
*/
FUNCTION FPuts(nHandle, cString, nLength, cDelim)
RETURN FWriteLn(nHandle, cString, nLength, cDelim)
/***
* DirEval( <cMask>, <bAction> ) --> aArray
* Apply a code block to each file matching a skeleton
*
* Tim Wong
*/
FUNCTION DirEval( cMask, bAction )
RETURN AEVAL( DIRECTORY(cMask), bAction )
/***
* FileTop( <nHandle> ) --> nPos
* Position the file pointer to the first byte in a binary file and return
* the new file position (i.e., 0).
*
*/
FUNCTION FileTop(nHandle)
RETURN FSEEK(nHandle, 0)
/***
* FileBottom( <nHandle> ) --> nPos
* Position the file pointer to the last byte in a binary file and return
* the new file position
*
*/
FUNCTION FileBottom(nHandle)
RETURN FSEEK(nHandle, 0, FS_END)
/***
* FilePos( <nHandle> ) --> nPos
* Report the current position of the file pointer in a binary file
*
*/
FUNCTION FilePos(nHandle)
RETURN FSEEK(nHandle, 0, FS_RELATIVE)
/***
* FileSize( <nHandle> ) --> nBytes
* Return the size of a binary file
*
*/
FUNCTION FileSize( nHandle )
LOCAL nCurrent, nLength
// Get file position
nCurrent := FilePos(nHandle)
// Get file length
nLength := FSEEK(nHandle, 0, FS_END)
// Reset file position
FSEEK(nHandle, nCurrent)
RETURN nLength
/***
* FReadLn( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cLines
* Read one or more lines from a text file
*
* NOTE: Line length includes delimiter, so max line read is
* (nLineLength - LEN( cDelim ))
*
* NOTE: Return value includes delimiters, if delimiter was read
*
* NOTE: nLines defaults to 1, nLineLength to 80 and cDelim to CRLF
*
* NOTE: FERROR() must be checked to see if FReadLn() was successful
*
* NOTE: FReadLn() returns "" when EOF is reached
*
*/
FUNCTION FReadLn( nHandle, nLines, nLineLength, cDelim )
LOCAL nCurPos, nFileSize, nChrsToRead, nChrsRead
LOCAL cBuffer, cLines
LOCAL nCount
LOCAL nEOLPos
IF nLines == NIL
nLines := 1
ENDIF
IF nLineLength == NIL
nLineLength := 80
ENDIF
IF cDelim == NIL
cDelim := CHR(13) + CHR(10)
ENDIF
nCurPos := FilePos( nHandle )
nFileSize := FileSize( nHandle )
// Make sure no attempt is made to read past EOF
nChrsToRead := MIN( nLineLength, nFileSize - nCurPos )
cLines := ''
nCount := 1
DO WHILE (nCount <= nLines) .AND. ( nChrsToRead != 0 )
cBuffer := SPACE( nChrsToRead )
nChrsRead := FREAD( nHandle, @cBuffer, nChrsToRead )
// Check for error condition
IF ! (nChrsRead == nChrsToRead)
// Error!
// In order to stay conceptually compatible with the other
// low-level file functions, force the user to check FERROR()
// (which was set by the FREAD() above) to discover this fact
//
nChrsToRead := 0
ENDIF
nEOLPos := AT( cDelim, cBuffer )
// Update buffer and current file position
IF nEOLPos == 0
cLines += LEFT( cBuffer, nChrsRead )
nCurPos += nChrsRead
ELSE
cLines += LEFT( cBuffer, ( nEOLPos + LEN( cDelim ) ) - 1 )
nCurPos += ( nEOLPos + LEN( cDelim ) ) - 1
FSEEK( nHandle, nCurPos, FS_SET )
ENDIF
// Make sure we don't try to read past EOF
IF (nFileSize - nCurPos) < nLineLength
nChrsToRead := (nFileSize - nCurPos)
ENDIF
nCount++
ENDDO
RETURN cLines
/***
* FileEval( <nHandle>, [<nLineLength>], [<cDelim>], ;
* <bBlock>,
* [<bForCondition>],
* [<bWhileCondition>],
* [<nNextLines>],
* [<nLine>],
* [<lRest>] ) --> NIL
* Apply a code block to lines in a binary file using DBEVAL() as a model.
* If the intent is to modify the file, the output must be written to a
* temporary file and copied over the original when done.
*
* NOTE: <bBlock>, <bForCondition> and <bWhileCondition> are passed a
* line of the file
*
* NOTE: The defaults for nLineLength and cDelim are the same as those
* for FReadLn()
*
* NOTE: The default for the rest of the parameters is that same as for
* DBEVAL().
*
* NOTE: Any past EOF requests (nLine > last line in file, etc.) are ignored
* and no error is generated. The file pointer will be left at EOF.
*
* NOTE: Check FERROR() to see if it was successful
*
* Author: Craig Ogg
*
*/
PROCEDURE FileEval( nHandle, nLineLength, cDelim, bBlock, bFor, bWhile, ;
nNextLines, nLine, lRest )
LOCAL cLine
LOCAL lEOF := .F.
LOCAL nPrevPos
IF bWhile == NIL
bWhile := {|| .T.}
ENDIF
IF bFor == NIL
bFor := {|| .T.}
ENDIF
// lRest == .T. means stay where I am. Anything else means start from
// the top of the file
//
IF ! ( ( VALTYPE(lRest) == 'L' ) .AND. ( lRest == .T. ) )
FileTop( nHandle )
ENDIF
BEGIN SEQUENCE
IF nLine != NIL
// Process only that one record
nNextLines := 1
FileTop( nHandle )
IF nLine > 1
cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
IF FERROR() != 0
BREAK
ENDIF
lEOF := ( cLine == "" )
nLine--
ENDIF
// Move to that record (nLine will equal 1 when we are there)
DO WHILE ( ! lEOF ) .AND. (nLine > 1)
cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
IF FERROR() != 0
BREAK
ENDIF
lEOF := ( cLine == "" )
nLine--
ENDDO
ENDIF
// Save starting position
nPrevPos := FilePos( nHandle)
// If there is more to read from here, get the first line for comparison
// and potential processing
//
IF ( ! lEOF ) .AND. (nNextLines == NIL .OR. nNextLines > 0)
cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
IF FERROR() != 0
BREAK
ENDIF
lEOF := ( cLine == "" )
ENDIF
DO WHILE ( ! lEOF ) .AND. EVAL( bWhile, cLine ) ;
.AND. (nNextLines == NIL .OR. nNextLines > 0)
IF EVAL( bFor, cLine )
EVAL( bBlock, cLine )
ENDIF
// Save start of line
nPrevPos := FilePos( nHandle )
// Read next line
cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
IF FERROR() != 0
BREAK
ENDIF
lEOF := ( cLine == "" )
IF nNextLines != NIL
nNextLines--
ENDIF
ENDDO
// If the reason for ending was that I ran past the WHILE or the number
// of lines specified, back up to the beginning of the line that failed
// so that there is no gap in processing
//
IF ( ! EVAL( bWhile, cLine ) ) .OR. ;
( (nNextLines != NIL) .AND. (nNextLines == 0) )
FSEEK( nHandle, nPrevPos, FS_SET )
ENDIF
END SEQUENCE
RETURN
/***
* FEof( <nHandle> ) --> lBoundary
* Determine if the current file pointer position is the last
* byte in the file
*
*/
FUNCTION FEof( nHandle )
RETURN (IF(FileSize(nHandle) == FilePos(nHandle), .T., .F. ))
/***
* FWriteLn( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
* Write a line to a text file at the current file pointer position.
*
* NOTE: Check FERROR() for the error
*
* NOTE: nLength defaults to length of entire string + delim, cDelim
* defaults to CHR(13) + CHR(10)
*
* NOTE: Return value includes length of delimiter
*
*/
FUNCTION FWriteLn( nHandle, cString, nLength, cDelim )
IF cDelim == NIL
cString += CHR(13) + CHR(10)
ELSE
cString += cDelim
ENDIF
RETURN FWRITE( nHandle, cString, nLength )
/****
* Function: FSize(cFileName) -->NUMERIC
* Purpose : Determines file size in bytest
* Date Created: 03/10/93
*/
FUNCTION FSize(cFile)
LOCAL nHandle := 0,;
nSize := 0,;
nError
BEGIN SEQUENCE
IF valtype(cFile) <> "C"
alert("ERROR: Usage: <Fsize> <Filename.ext>;"+GetDosErr(1000))
BREAK
ENDIF
nHandle := fopen( cFile,if(set(_SET_EXCLUSIVE),FO_READWRITE,FO_SHARED))
IF (nError := ferror()) <> 0
alert(,,upper(cFile)+"ERROR:" + GetDosErr(nError))
BREAK
ENDIF
nSize := FileSize(nHandle)
IF nError == 0
fclose(nHandle)
ENDIF
END SEQUENCE
RETURN nSize